import matplotlib.pyplot as plt
import numpy as np
import request
from matplotlib.ticker import FormatStrFormatter
import oss2  
import io
import datetime
from scipy.optimize import curve_fit

@app.route('/area_2d/', methods=["POST"])
@cross_origin()
def area_2d():
    # object_name, camera_id, loc, grid_len, length, rate, angle=1, h=-3950
    object_name = request.form.get('object_name')
    camera_id = request.form.get('camera_id')
    loc = request.form.get('loc', (-1000, 4000))
    grid_len = request.form.get('grid_len', 20)
    length = request.form.get('length', 6000)
    rate = request.form.get('rate', 1.0)
    recalibrate = request.form.get('recalibrate', False)
    if type(recalibrate) == str:
        recalibrate = True
    # angle = request.form.get('angle', 1)
    # h = request.form.get('h', -3950)
    # print(object_name, camera_id, loc, grid_len, length, rate)
    # auth = oss2.Auth('LTAI5tGPkHofe2wfSkE23csC', 'Tvw6H18pOrlaOzXYI0OcMu87XzbFwT')
    # auth = oss2.Auth('LTAI5t7crFYdigVucc4rtyRr', '5kC42wvQ9HbYqWJRdF15MTRoeP5CZa')
    # bucket = oss2.Bucket(auth, 'oss-cn-hangzhou.aliyuncs.com', 'raspberryupload')
    auth = oss2.Auth('LTAI5t7crFYdigVucc4rtyRr', '5kC42wvQ9HbYqWJRdF15MTRoeP5CZa')
    bucket = oss2.Bucket(auth, 'https://oss-cn-shanghai.aliyuncs.com', 'raspberryupload')
    if not bucket.object_exists(object_name):
        return 'The file does not exist, please check again!'

    content = bucket.get_object(object_name)
    data = content.read()
    file = io.BytesIO(data)
    data = np.loadtxt(file, delimiter=',')

    if not bucket.object_exists('data/%s/adjust_info.txt' % camera_id) or recalibrate:
        angles = data[:, 2]
        distances = data[:, 1]
        loc = (2500, 5500, -4500, -3500)
        pi = 3.141592653
        x = distances * np.sin(angles / 180 * pi)
        y = distances * np.cos(angles / 180 * pi)

        condition = (x > loc[0]) & (x < loc[1]) & (y > loc[2]) & (y < loc[3])
        x = x[condition]
        y = y[condition]

        min_std = 999999
        angle = 0
        for theta in range(-10, 11):
            x1 = x * np.cos(theta / 180 * pi) - y * np.sin(theta / 180 * pi)
            y1 = x * np.sin(theta / 180 * pi) + y * np.cos(theta / 180 * pi)
            std_theta = np.std(y1)
            if std_theta < min_std:
                min_std = std_theta
                angle = theta
                height = y1.mean()
        h = height
        adjust_info = str(angle) + ' ' + str(h)
        bucket.put_object('data/%s/adjust_info.txt' % camera_id, adjust_info)
    else:
        adjust_info = bucket.get_object('data/%s/adjust_info.txt' % camera_id)
        info = adjust_info.read()
        info = io.BytesIO(info)
        info = np.loadtxt(info)
        angle, h = int(info[0]), float(info[1])

    # 最大全景出图
    xmin = -10000
    xmax = 10000
    ymin = -10000
    ymax = 10000

    # 获取角度、距离和激光强度数据列
    angles = data[:, 2]
    distances = data[:, 1]

    q = 0
    data_new = np.array([0, 0, 0])
    table_data = [
        ['距离', '角度'],
    ]
    n = len(angles)
    time_work = distances
    radar_status = angles
    for i in range(n):
        time_value = time_work[i] if i < len(time_work) else ''
        radar_value = radar_status[i] if i < len(radar_status) else ''
        table_data.append([time_value, radar_value])
    for i in range(100000, 360000, 50):

        i = i / 1000
        distances = [x[0] for x in table_data[1:] if i < x[1] < i + (50 / 1000)]
        # 判断distances长度是否为0
        if len(distances) == 0:
            continue  # 跳过当前循环进入下一次循环
        average_distance = sum(distances) / len(distances)
        q = q + 1
        data_new = np.vstack((data_new, [q, average_distance, i]))

    angles = data_new[:, 2]
    distances = data_new[:, 1]
    pi = 3.141592653
    # x = distances * np.sin(angles / 180 * pi)*np.cos(45 / 180 * pi)
    x = distances * np.sin(angles / 180 * pi)
    y = distances * np.cos(angles / 180 * pi)

    # 旋转校准
    theta = angle
    x = x * np.cos(theta / 180 * pi) - y * np.sin(theta / 180 * pi)
    y = x * np.sin(theta / 180 * pi) + y * np.cos(theta / 180 * pi)

    condition_all = (x > xmin) & (x < xmax) & (y > ymin) & (y < -500)
    x_all = x[condition_all]
    y_all = y[condition_all]

    condition = (x > loc[0]) & (x < loc[1]) & (y > ymin) & (y < -500)
    x = x[condition]
    y = y[condition]
    x -= x_all.min()
    y -= h

    x_all -= x_all.min()
    y_all -= h

    condition_wall = (x_all > 300) & (x_all < 450) & (y_all > y.min()) & (y_all < 2500)
    x_wall = x_all[condition_wall]
    y_wall = y_all[condition_wall]

    area = 0
    height = []
    dict = {}

    for i in range(550, 3261, grid_len):
        for j in range(len(x)):
            if x[j] >= i and x[j] < i + grid_len:
                if i not in dict:
                    dict[i] = [j]
                else:
                    dict[i].append(j)

    for key in list(dict.keys()):
        if key + grid_len in dict.keys():
            left = key
            break
        else:
            del dict[key]

        # 拟合墙壁那段直线
    def func(x, a, b):
        return a * x + b

    popt, pcov = curve_fit(func, x_wall, y_wall)
    a, b = popt
    # x_a = np.arange(300, min(dict.keys()), 20)   #  需要填补的x区间
    gap = 0
    start = left - gap if gap else 300
    x_a = np.arange(start, left, 20)  # 需要填补的x区间
    y_a = a * x_a + b
    y_a = np.where(y_a < 0, 0, y_a)  # 拟合出直线点的y坐标
    # exit()

    # x_fill = [y[max(dict[min(dict.keys())])]] * len(y_a)
    x_fill = [y[min(dict[left])]] * len(y_a)
    x_fill = x_fill - y_a  # 填充的高度
    x_fill = np.where(x_fill < 0, 0, x_fill)

    for key in dict:
        h = 0
        for i in dict[key]:
            h = max(h, y[i])
        height.append(h)

    for i in height:
        area += 20 * i
    volume = area / 1e6 * length / 1000 * rate
    area /= 1e6

    fig = plt.figure(figsize=(100, 100))
    ax1 = fig.add_subplot(111)
    scatter = ax1.scatter(x_all, y_all, s=0.05, c='blue')
    # scatter = ax1.scatter(x, y, s=0.05)
    ax1.set_title("二维展示")
    ax1.set_xlabel('x轴(毫米)')
    ax1.set_ylabel('y轴(毫米)')

    # 设置横轴刻度位置和标签
    x_ticks = np.arange(0, max(x_all)+500, 500)
    ax1.set_xticks(x_ticks)
    ax1.set_xticklabels(x_ticks)
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%d'))

    # 设置纵轴刻度位置和标签
    y_ticks = np.arange(0, max(y_all)+500, 500)
    ax1.set_yticks(y_ticks)
    ax1.set_yticklabels(y_ticks)
    ax1.yaxis.set_major_formatter(FormatStrFormatter('%d'))
    x = []
    for i in dict.keys():
        x.append(int(i)+10)
    plt.bar(x, height, width=20, alpha=0.5, color='c')
    plt.bar(x_a, x_fill, width=20, bottom=y_a, alpha=0.5, color='c')
    ax1.set_aspect('equal')
    plt.title('The area is %.5f' % area)
    # plt.show()
    buffer = io.BytesIO()
    fig.savefig(buffer, format='png')
    buffer.seek(0)
    # return area
    bucket.put_object('data/%s/%s.png' % (camera_id, datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")), buffer.getvalue())
    plt.close()
    return str(area)